using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ProjectEuler.Core.Helpers;

namespace ProjectEuler.Core
{
    public class Problem37 : IProjectEulerProblem
    {
        private const int MAX_TRUNCATABLE_PRIMES = 11;      // given: 'only eleven primes that are both truncatable from left to right and right to left'
        
        protected IList<int> TruncatablePrimes()
        {
            var list = new List<int>();
            var num = 8;                                    // given '2, 3, 5, and 7 are not considered to be truncatable primes'
            while(list.Count < MAX_TRUNCATABLE_PRIMES)
            {
                if(IsTruncatablePrime(num))
                {
                    list.Add(num);
                }
                num++;
            }
            return list;
        }

        protected bool IsTruncatablePrime(int num)
        {
            return IsTruncatablePrimeDirection(num, RemoveLeftmostDigit) && IsTruncatablePrimeDirection(num, RemoveRightMostDigit);
        }

        protected int RemoveLeftmostDigit(int n)
        {
            return int.Parse(n.ToString().Remove(0, 1));
        }

        protected int RemoveRightMostDigit(int n)
        {
            return int.Parse(n.ToString().Substring(0, n.ToString().Length - 1));
        }

        private static bool IsTruncatablePrimeDirection(int num, Func<int, int> truncateMethod)
        {
            var isPrime = MathHelper.IsPrime(num);
            if (num >= 10)
            {
                var next = truncateMethod(num);
                isPrime = isPrime && IsTruncatablePrimeDirection(next, truncateMethod);
            }
            return isPrime;
        }

        public int Number
        {
            get { return 37; }
        }

        public string Description
        {
            get { return "Find the sum of the only eleven primes that are both truncatable from left to right and right to left."; }
        }

        public string Answer
        {
            get { return TruncatablePrimes().Sum().ToString(); }
        }
    }

    [TestFixture]
    public class Problem37Tests : Problem37
    {
        [Test]
        public void Then_3797_should_be_a_truncatable_prime()
        {
            Assert.AreEqual(true, IsTruncatablePrime(3797));
        }
    }
}